package xj.graph2d.shapes.block;

import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

import xj.graph2d.DrawShape;
import xj.graph2d.DrawShapeBase;
import xj.graph2d.GraphNodeBase;
import xj.graph2d.shapes.BarShape;

public class HBlockShape 
  extends BlockShape {

  public HBlockShape() { 
    this(false);
  }

  public HBlockShape(boolean createComp) { 
    super(createComp);
    setAllowRotation(false);
    setSymetricResize(false);
    setAcceptSubshape(true);
    showExpansionBar = false; 
    showSideBar = false; 
  }

  public HBlockShape(float x1, float y1, float x2, float y2) { 
    this(x1, y1, x2, y2, false);
  }

  public HBlockShape(float x1, float y1, float x2, float y2,
		     boolean createComp) { 
    super(x1, y1, x2, y2, createComp);
    setAllowRotation(false);
    setSymetricResize(false);
    setAcceptSubshape(true);
    showExpansionBar = false; 
    showSideBar = false; 
  }

  @Override
  public DrawShape makeInstance() {
    return new HBlockShape(comp != null);
  }

  @Override
  public void copyTo(DrawShapeBase s) 
    throws CloneNotSupportedException {
    super.copyTo(s);
    if (s instanceof HBlockShape) {
      HBlockShape b = (HBlockShape) s;

    }
  }

  // pos is the insertion location of the new node
  @Override
  public boolean positionSubNode(GraphNodeBase node,  Point2D pos) {
    //System.out.println("HBlockShape.positionSubNode(node, pos) " + node + " " + pos);
    boolean changed = false; 
    if (node != null && 
	subshapes != null) {
      
      if (!isExpanded()) { 
	expand();
      }

      if (blockType != IF_BLOCK) { 
	if (node instanceof StatementShape) { 
	  subshapes.remove(node);
	  int n = subshapes.size();

	  if (isDefaultCaseBlock(node)) { 
	    // always put default case at last 
	    DrawShape s0 = findDefaultCaseBlock();
	    if (s0 != null) { 
	      removeShape(s0); // update doc tree
	      changed = true; 
	    }	
	    subshapes.add(node);      
	  } else { 	   
	    float x0 = (float) node.getCenterPosition().getX(); 
	    if (pos != null && 
		node.getBounds().contains(pos.getX(), pos.getY())) { 
	      x0 = (float) pos.getX();
	    }	  
	    //System.out.println("BlockShape.positionSubNode(node, pos) y0=" + y0);	 
	    int i = 0; 
	    for (; i < n; i++) {
	      DrawShape s = subshapes.get(i);
	      if (s instanceof StatementShape) { 
		if (isDefaultCaseBlock(s)) { 
		  break; 
		}
		float x = (float) s.getCenterPosition().getX();		
		//System.out.println("BlockShape.positionSubNode(node, pos) y[" + i + "]=" + y)
		if (x > x0) { 
		  break; 
		}
	      }
	    }
	    subshapes.add(i, node);      
	  }
	} else if (node instanceof BarShape) { 
	  int role = node.getRole();
	  if (blockType == IF_BLOCK) { 
	    if (role == CONDITION) { 
	      DrawShape s0 = findInRole(CONDITION);
	      if (s0 != null && s0 != node) { 
		removeShape(s0); // update doc tree
		changed = true; 
	      }
	    }
	  } 
	}
      }
      //System.out.println("BlockShape.positionSubNode(node, pos) insert at:" + i);

      float left = (float) Math.min(p1.getX(), p2.getX());
      float top = (float) Math.min(p1.getY(), p2.getY());
      float width = (float) Math.abs(p1.getX() - p2.getX());
      int minw = getMinWidth();
      if (width < minw) { 
	width = minw;
      }

      layoutStatement(top, left, width);
      positionExpressions();

      adjustParentLayout();
    }
    return changed;
  }


  // layout horizontally 
  @Override
  public Rectangle2D layoutStatement(float top, float left, float width,
				     boolean fit) {
    //System.out.println("HBlockShape.layoutStatement()");

    float x = left + GAP;
    /*
    if (showExpansionBar) { 
      x += expansionBarWidth;
      w -= expansionBarWidth;
    }
    if (showSideBar) { 
      //x += sideBarWidth;
      w -= sideBarWidth;
    }
    */

    float y = top + GAP;
    if (showHeader) { 
      y += headerHeight; 
    }        
    float bottom = y;  
    if (subshapes != null) {
      int count = getStatementCount();
      if (count > 0) { 	
	boolean done = false; 
	if (blockType == IF_BLOCK && 
	    count == 2 && 
	    width > MIN_WIDTH * 2 + GAP * 3) { 
	  StatementShape s0 = getFirstStatement();
	  StatementShape s1 = getLastStatement();
	  if (s0 instanceof BlockShape && 
	      s1 instanceof BlockShape) { 
	    BlockShape b0 = (BlockShape) s0; 
	    BlockShape b1 = (BlockShape) s1; 
	    if (b0.getStatementCount() > 0 &&
		b1.getStatementCount() == 0) { 
	      float w0 = width - GAP * 3 - MIN_WIDTH;
	      float w1 = MIN_WIDTH;
	      Rectangle2D rect = s0.layoutStatement(y, x, w0);	    
	      //x = (float) (rect.getX() + rect.getWidth()) + GAP; 
	      x = x + w0 + GAP; 
	      bottom = Math.max(bottom, (float) (rect.getY() + rect.getHeight()));
	      rect = s1.layoutStatement(y, x, w1);	    
	      bottom = Math.max(bottom, (float) (rect.getY() + rect.getHeight()));
	      done = true;
	    }
	  }
	} 

	if (!done) { 
	  float minw = getMinWidth();
	  float dw = (width - minw);
	  if (dw < 0) { 
	    dw = 0; 
	  }
	  // column width 
	  //float w = (width - GAP * (count + 1)) / count;  
	  int n = subshapes.size();
	  for (int i = 0; i < n; i++) {
	    DrawShape s = subshapes.get(i);
	    if (s.isVisible()) { 
	      if (s instanceof StatementShape) {
		StatementShape stmt = (StatementShape) s;
		float w0 = stmt.getMinWidth();
		float w = w0; 
		if (dw > 0) { 
		  w += (w0 / (minw - GAP * (count + 1))) * dw; 
		}
		Rectangle2D rect = stmt.layoutStatement(y, x, w);	    
		//x = (float) (rect.getX() + rect.getWidth()) + GAP; 
		x = x + w + GAP; 
		bottom = Math.max(bottom, (float) (rect.getY() + rect.getHeight()));
	      }
	    }
	  }
	}
      }
      /*
      if (!expanded) {   }
      */
    }  

    bottom += GAP;
    if (showFooter) { 
      bottom += footerHeight; 
    }

    float minHeight = MIN_HEIGHT + 2 * GAP; 
    if (showHeader) { 
      minHeight += headerHeight; 
    }
    if (showFooter) { 
      minHeight += footerHeight; 
    }
    if (bottom < top + minHeight) { 
      bottom = top + minHeight;
    }

    if (!fit) { 
      float height = (float) Math.abs(p1.getY() - p2.getY());
      if (height > (bottom - top)) {
	bottom = top + height; 
      }
    }
    
    setEnds(left, top, left + width, bottom);
    return bounds; 
  }


  @Override
  public int getMinWidth() { 
    int minw = MIN_WIDTH;
    if (subshapes != null) {
      int count = getStatementCount();
      if (count > 0) { 	
	StatementShape s0 = getFirstStatement();
	StatementShape s1 = getLastStatement();
	if (blockType == IF_BLOCK && 
	    count == 2 &&
	    s0 instanceof BlockShape && 
	    s1 instanceof BlockShape) { 
	  BlockShape b0 = (BlockShape) s0; 
	  BlockShape b1 = (BlockShape) s1; 
	  if (b0.getStatementCount() > 0 &&
	      b1.getStatementCount() == 0) {
	    return b0.getMinWidth() + MIN_WIDTH + 3 * GAP; 
	  }
	}

	if (count == 1) { 
	  return s0.getMinWidth() + 2 * GAP; 
	}
      
	int n = subshapes.size();
	minw = GAP; 
	for (int i = 0; i < n; i++) {
	  DrawShape s = subshapes.get(i);
	  if (s instanceof StatementShape) {
	    StatementShape stmt = (StatementShape) s;
	    minw += (stmt.getMinWidth() + GAP);
	  }
	}
      }
    }
    return minw;
  }

}